package org.truenewx.tnxjee.core.util;

import java.util.HashSet;
import java.util.Set;
import java.util.function.Predicate;

/**
 * 异常工具类
 *
 * @author jianglei
 */
public class ExceptionUtil {

    private ExceptionUtil() {
    }

    public static RuntimeException toRuntimeException(Throwable t) {
        if (t instanceof RuntimeException) {
            return (RuntimeException) t;
        }
        Throwable cause = t.getCause();
        if (cause instanceof RuntimeException) {
            return (RuntimeException) cause;
        }
        return new RuntimeException(t);
    }

    public static void throwRuntimeException(Throwable t) {
        if (t != null) {
            throw toRuntimeException(t);
        }
    }

    public static Throwable getRootCause(Throwable t) {
        return traverseCause(t, null);
    }

    /**
     * 遍历异常的原因，直到遇到指定断言通过的原因或根原因为止
     *
     * @param t         异常
     * @param predicate 断言
     * @return 断言通过的原因或根原因
     */
    public static Throwable traverseCause(Throwable t, Predicate<Throwable> predicate) {
        if (t == null) {
            return null;
        }
        Throwable result = t;
        Set<Throwable> visited = new HashSet<>();
        visited.add(result);
        while (result.getCause() != null) {
            Throwable cause = result.getCause();
            if (!visited.add(cause)) {
                break; // 发现循环引用时停止遍历
            }
            result = cause;
            if (predicate != null && predicate.test(result)) {
                break; // 断言通过时停止遍历
            }
        }
        return result;
    }

}
